---
title: Self-Hosted Deployment
description: Learn how to deploy your Motia project to production using motia-docker
---

import VideoPlayer from '@/components/VideoPlayer';

<VideoPlayer videoPath="https://assets.motia.dev/videos/mp4/site/v1/8-motia-self-hosting.mp4" gifPath="https://assets.motia.dev/images/gifs/v1/8-motia-self-hosting.gif" title="Self-Hosting & Deployment" className="mb-8" />

Run your Motia app in Docker containers. Same environment everywhere - dev, staging, production.

<Callout type="warn">You need motia package **0.5.2-beta.101 or higher**</Callout>

## Quick Start

<Callout type="info">
**Important:** Run these commands from your project root (where your `package.json` is).
</Callout>

<Steps>
<Step>
#### Navigate to your project

```bash
cd /path/to/your/motia-project
```

Make sure you see `package.json` when you run `ls`.

</Step>
<Step>
#### Setup Docker files

```bash
npx motia@latest docker setup
```

This creates `Dockerfile` and `.dockerignore` in your project.

</Step>
<Step>
#### Build and run

```bash
npx motia@latest docker run --project-name my-app
```

Replace `my-app` with your project name.

</Step>
<Step>
#### Check it works

Open [http://localhost:3000](http://localhost:3000) in your browser.

For more options:
```bash
npx motia@latest docker run --help
```

</Step>
</Steps>

<Callout type="error">
**Getting `ENOENT: no such file or directory, open package.json`?**

You're not in your project directory. Run `cd /path/to/your/project` first.
</Callout>

---

## Manual Docker Setup

Want more control? Build it yourself.

The `docker setup` command creates a Dockerfile for you, but here's what's in it:

```dockerfile title="Dockerfile"
# Use Motia's base image (has Node + Python ready)
FROM motiadev/motia:latest

# For AWS Lightsail or other ARM platforms, use:
# FROM --platform=linux/arm64 motiadev/motia:latest

# Copy package files
COPY package*.json ./

# Install dependencies
RUN npm ci --only=production

# Copy your app
COPY . .

# If you have Python steps, uncomment this line:
# RUN npx motia@latest install

# Expose the port
EXPOSE 3000

# Start your app
CMD ["npm", "run", "start"]
```

### Python Steps?

If you have Python steps, uncomment this line in the Dockerfile:

```dockerfile
RUN npx motia@latest install
```

And make sure you have a `requirements.txt` file in your project.

### .dockerignore

Create a `.dockerignore` file to keep your image small:

```bash
# Git
.git
.gitignore

# Python
__pycache__/
*.py[cod]
*$py.class
*.so
.Python
env/
venv/
ENV/

# Node
node_modules/
npm-debug.log
yarn-debug.log
yarn-error.log

# IDE
.vscode/
.idea/
*.swp
*.swo

# Local development
.env

# OS generated files
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db
```

---

## Build and Run Manually

### Build your image

```bash
docker build -t my-motia-app .
```

### Run it

```bash
docker run -it --rm -p 3000:3000 my-motia-app
```

Open [http://localhost:3000](http://localhost:3000) - your app should be running!

---

## Troubleshooting

### Using Minimal Docker Images (node:24-slim)

If you're using a minimal Docker image like `node:24-slim` instead of the official `motiadev/motia:latest` image, you may encounter errors when creating a new Motia project or running `motia dev`, 
because the `redis-memory-server` package may require build tools (`make`, `gcc`, etc.) to compile Redis from source. These are not included in minimal images.

**Solution:** Install the required dependencies before running Motia:

```bash
docker run --rm node:24-slim bash -c "
  apt-get update && apt-get install -y ca-certificates git build-essential &&
  npx motia@latest create my-app --template starter-typescript
"
```

**Alternative:** Install Redis system package to avoid compilation:

```bash
docker run --rm node:24-slim bash -c "
  apt-get update && apt-get install -y ca-certificates git redis-server &&
  export REDISMS_SYSTEM_BINARY=/usr/bin/redis-server &&
  npx motia@latest create my-app --template starter-typescript
"
```

**Recommended:** Use the official `motiadev/motia:latest` image which includes all required dependencies, or use the full `node:24` image instead of `node:24-slim`.

---

## Deploy to Cloud

### AWS Lightsail

Lightsail needs ARM. Update your Dockerfile:

```dockerfile
FROM --platform=linux/arm64 motiadev/motia:latest
```

Then build and deploy.

### Railway

Connect your GitHub repo. Railway detects the Dockerfile automatically.

### Fly.io

Create `fly.toml`:

```toml
app = "my-motia-app"

[build]
  dockerfile = "Dockerfile"

[[services]]
  internal_port = 3000
  protocol = "tcp"
```

Deploy: `fly deploy`

### Render

Create a Web Service, point to your repo. Render builds automatically.

---

## Configuring Adapters for Production

When deploying multiple Motia instances, you need distributed adapters to share state, events, and streams across instances. Without them, each instance operates in isolation.

### When to Use Distributed Adapters

**Use default adapters when:**
- Running a single Motia instance
- Development and testing
- Simple deployments

**Use distributed adapters when:**
- Running multiple Motia instances (horizontal scaling)
- Production deployments requiring high availability
- Need shared state/events/streams across instances

### Docker Compose with Redis

For production deployments, use Docker Compose to run Motia with Redis:

```yaml title="docker-compose.yml"
version: '3.8'

services:
  redis:
    image: redis:7-alpine
    ports:
      - "6379:6379"
    volumes:
      - redis-data:/data

  motia:
    build: .
    ports:
      - "3000:3000"
    environment:
      - REDIS_HOST=redis
      - REDIS_PORT=6379
      - RABBITMQ_URL=amqp://rabbitmq:5672
    depends_on:
      - redis
      - rabbitmq

  rabbitmq:
    image: rabbitmq:3-management-alpine
    ports:
      - "5672:5672"
      - "15672:15672"
    volumes:
      - rabbitmq-data:/var/lib/rabbitmq

volumes:
  redis-data:
  rabbitmq-data:
```

### Configure Adapters in motia.config.ts

Update your configuration to use distributed adapters:

```typescript title="motia.config.ts"
import { config } from '@motiadev/core'
import { RedisStateAdapter } from '@motiadev/adapter-redis-state'
import { RedisStreamAdapterManager } from '@motiadev/adapter-redis-streams'
import { RabbitMQEventAdapter } from '@motiadev/adapter-rabbitmq-events'
import { RedisCronAdapter } from '@motiadev/adapter-redis-cron'

export default config({
  adapters: {
    state: new RedisStateAdapter({
      host: process.env.REDIS_HOST || 'localhost',
      port: parseInt(process.env.REDIS_PORT || '6379'),
    }),
    streams: new RedisStreamAdapterManager({
      host: process.env.REDIS_HOST || 'localhost',
      port: parseInt(process.env.REDIS_PORT || '6379'),
    }),
    events: new RabbitMQEventAdapter({
      url: process.env.RABBITMQ_URL || 'amqp://localhost:5672',
      exchangeName: process.env.RABBITMQ_EXCHANGE || 'motia.events',
      exchangeType: 'topic',
    }),
    cron: new RedisCronAdapter({
      host: process.env.REDIS_HOST || 'localhost',
      port: parseInt(process.env.REDIS_PORT || '6379'),
    }),
  },
})
```

### Install Adapter Packages

Add the adapter packages to your `package.json`:

```bash
npm install @motiadev/adapter-redis-state \
            @motiadev/adapter-redis-streams \
            @motiadev/adapter-rabbitmq-events \
            @motiadev/adapter-redis-cron
```

### Scaling Multiple Instances

With distributed adapters configured, you can scale to multiple instances:

```yaml title="docker-compose.yml"
services:
  motia-1:
    build: .
    ports:
      - "3000:3000"
    environment:
      - REDIS_HOST=redis
      - REDIS_PORT=6379
    depends_on:
      - redis

  motia-2:
    build: .
    ports:
      - "3001:3000"
    environment:
      - REDIS_HOST=redis
      - REDIS_PORT=6379
    depends_on:
      - redis

  motia-3:
    build: .
    ports:
      - "3002:3000"
    environment:
      - REDIS_HOST=redis
      - REDIS_PORT=6379
    depends_on:
      - redis
```

All instances share the same state, events, and streams through Redis and RabbitMQ.

<Callout type="warn">
Without distributed adapters, each Motia instance has isolated state and events. Use Redis/RabbitMQ adapters for multi-instance deployments.
</Callout>

[Learn more about adapters →](/docs/development-guide/adapters/usage)

---

## Resources

- [Docker Hub](https://hub.docker.com/r/motiadev/motia) - Official Motia image
- [Example Project](https://github.com/MotiaDev/motia-examples/tree/main/examples/motia-docker) - Full deployment example
- [CLI Reference](/docs/development-guide/cli#docker) - All docker commands
